﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Eksponent.CropUp
{
    public class ImageSizeArguments
    {
        public static readonly CultureInfo UrlCulture = new CultureInfo("en-US");

        static Regex _argMatcher = new Regex(@"\-$|(
            (
                (?<Width>(\-|[0-9]+))
                x
                (?<Height>(\-|[0-9]+))
            )?
            (g\(
                (?<GravityX>[0-9]+(\.[0-9]+)?)
                ,
                (?<GravityY>[0-9]+(\.[0-9]+)?)
            \))?
            (b\(
                (?<BoxLeft>[0-9]+(\.[0-9]+)?)
                ,
                (?<BoxTop>[0-9]+(\.[0-9]+)?)
                ,
                (?<BoxRight>[0-9]+(\.[0-9]+)?)
                ,
                (?<BoxBottom>[0-9]+(\.[0-9]+)?)
            \))?
            (?<Alias>[a-z]+)?
            (?<CropMode>[A-Y])?
            (?<Zoom>Z)?
        )", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);

        public int? Width { get; set; }
        public int? Height { get; set; }

        public PointF? Gravity { get; set; }

        public RectangleF? Box { get; set; }

        public CropUpMode CropMode { get; set; }

        public string CropAlias { get; set; }

        public bool Zoom { get; set; }


        public static ImageSizeArguments Parse(string args)
        {
            var isa = new ImageSizeArguments();

            var argsMatch = _argMatcher.Match(args);
            int maxWidth, maxHeight;
            isa.Width = int.TryParse(argsMatch.Groups["Width"].Value, out maxWidth) ? maxWidth : (int?)null;
            isa.Height = int.TryParse(argsMatch.Groups["Height"].Value, out maxHeight) ? maxHeight : (int?)null;

            if( argsMatch.Groups["GravityX"].Success)
            {
                isa.Gravity = new PointF(float.Parse(argsMatch.Groups["GravityX"].Value, UrlCulture), float.Parse(argsMatch.Groups["GravityY"].Value, UrlCulture));                
            }

            if (argsMatch.Groups["BoxLeft"].Success)
            {
                var tl = new PointF(float.Parse(argsMatch.Groups["BoxLeft"].Value, UrlCulture), float.Parse(argsMatch.Groups["BoxTop"].Value, UrlCulture));
                var br = new PointF(float.Parse(argsMatch.Groups["BoxRight"].Value, UrlCulture), float.Parse(argsMatch.Groups["BoxBottom"].Value, UrlCulture));
                isa.Box = new RectangleF(tl.X, tl.Y, br.X - tl.X, br.Y - tl.Y);
            }

            isa.CropMode = CropModeHelper.FromString(argsMatch.Groups["CropMode"].Value);
            isa.CropAlias = argsMatch.Groups["Alias"].Value;
            
            isa.Zoom = argsMatch.Groups["Zoom"].Success;
            return isa; 
        }

        public override string ToString()
        {
            var args = new StringBuilder();
            if (Width.HasValue || Height.HasValue)
            {
                args.Append(Width.HasValue ? "" + Width : "-")
                    .Append("x").Append(Height.HasValue ? "" + Height : "-");
            }

            if( Gravity.HasValue )
            {
                var g = Gravity.Value;
                args.Append("g(").Append(g.X.ToString(UrlCulture)).Append(",").Append(g.Y.ToString(UrlCulture)).Append(")");
            }

            if( Box.HasValue )
            {
                var b = Box.Value;
                args.Append("b(").Append(b.Left.ToString(UrlCulture)).Append(",").Append(b.Top.ToString(UrlCulture))
                    .Append(",").Append(b.Right.ToString(UrlCulture)).Append(",").Append(b.Bottom.ToString(UrlCulture)).Append(")");
            }

            if (!string.IsNullOrEmpty(CropAlias))
            {
                args.Append(CropAlias.ToLower());
            }
            if (CropMode != CropUpMode.BestFit)
            {
                args.Append(CropModeHelper.ToString(CropMode));
            }
            if( Zoom )
            {
                args.Append("Z");
            }

            return args.Length == 0 ? "-" : args.ToString();
        }
    }
}
